#单例模式
#先了解 __init__() 初始化方法 __new__() 创建对象方法 object提供的静态方法 作用1 在内存中为对象分配空间 2返回对象调用 先于init执行
#new 返回了对象的地址 init才能初始化
class Animal(object):
    def __init__(self):
        print("初始方法")
    def __new__(cls, *args, **kwargs):
        print("new方法") #因为重写了new,所以这个时候没有返回对象的调用了
        res = super().__new__(cls) #调用了父方法的new,res保存了对象的地址,相当于对new方法进行了扩写
        return res
a1 = Animal()
#单例模式 一种常用的软件设计模式 目的确保某一个类中只存在一个实例对象 优点节省空间 缺点多线程时访问容易引发线程安全问题
#可以理解为 一个类只能创建一个对象
#比如你打开一个回收站页面,在点击回收站时还是之前打开的页面,只能存在一个回收站页面
#实现方法 1通过类方法@classmethod 2通过装饰器实现 3通过重写new方法(重点) 4通过导入模块实现
#通过重写new方法实现思路
#1 定义一个类属性用于存放对象地址
#2 重写new方法
#3 判断如果类属性为none 则存入new方法中返回的对象地址,否则返回类属性存的对象地址
#这样不管如何创建对象,使用的始终是同一个对象
class Cat(object):
    obj = None #1 定义一个类属性用于存放对象地址
    def __new__(cls, *args, **kwargs): #2 重写new方法
        if cls.obj is None: #3 判断如果类属性为none 则存入new方法中返回的对象地址,否则返回类属性存的对象地址
            cls.obj = super().__new__(cls)
        return cls.obj
c1 = Cat()
c2 = Cat()
print(id(c1), id(c2))
#因为init是通过new返回的对象创建的,所以每次新实例对象,类的属性是同一个,不会使obj重新赋值为None
#通过导入模块实现 模块就是天然的单例模式
#在一个模块中创建一个类,实例一个对象,其他文件通过起别名的方式访问同一个模块中的对象,不同别名使用的就是同一个对象
#from xxx import 对象 as a1
#from xxx import 对象 as a2
#a1和a2访问的是同一个对象
